package com.ruoyi.my.controller;

import com.alibaba.fastjson.JSONObject;
import com.mysql.cj.util.StringUtils;
import com.ruoyi.common.annotation.WebTakeTime;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.RetObjectDTO;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.my.domain.Shop;
import com.ruoyi.my.domain.WxFullUserInfo;
import com.ruoyi.my.domain.WxUserInfo;
import com.ruoyi.my.service.IshopService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信登录操作
 */
@Controller
@RequestMapping("/wx")
public class WxController extends BaseController {

    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private IshopService shopService;

    /**
     * 查询商家列表
     */
    @WebTakeTime
    @GetMapping("/shops")
    public TableDataInfo listForWx(Shop shop) {
        startPage();
        List<Shop> list = shopService.selectshopList(shop);
        return getDataTable(list);
    }

    /**
     * 微信登录
     */
    @WebTakeTime
    @ApiOperation(value = "微信登录")
    @PostMapping("/xcxLogin")
    @ResponseBody
    public Object loginByWeixin() {
        JSONObject jsonParam = getJsonRequest();
        WxFullUserInfo fullUserInfo = null;
        String code = "";
        if (!StringUtils.isNullOrEmpty(jsonParam.getString("code"))) {
            code = jsonParam.getString("code");
        }
        if (null != jsonParam.get("userInfo")) {
            fullUserInfo = jsonParam.getObject("userInfo", WxFullUserInfo.class);
        }
        if (null == fullUserInfo) {
            return AjaxResult.error("登录失败");
        }

        Map<String, Object> resultObj = new HashMap<String, Object>();
        WxUserInfo userInfo = fullUserInfo.getUserInfo();

        //获取openid
        String requestUrl = getWebAccess(code);//通过自定义工具类组合出小程序需要的登录凭证 code
        JSONObject sessionData = JSONObject.parseObject(HttpUtils.sendGet(requestUrl));

        if (null == sessionData || StringUtils.isNullOrEmpty(sessionData.getString("openid"))) {
            return AjaxResult.error("登录失败");
        }

        //验证用户信息完整性
        String sha1 = getSha1(fullUserInfo.getRawData() + sessionData.getString("session_key"));
        if (!fullUserInfo.getSignature().equals(sha1)) {
            return AjaxResult.error("登录失败");
        }

        String openid = sessionData.getString("openid");
        Date nowTime = new Date();
        SysUser userVo = saveSysUser(userInfo, openid, nowTime);
        resultObj.put("userInfo", userInfo);
        resultObj.put("user", userVo);

        /*登录下用户，方便后面获取用户信息*/
        String token = loginService.wxLogin(openid, openid);
        resultObj.put("token", token);
        /*把用户信息放入缓存中*/
//        setTokenInCache(userVo);
        return new RetObjectDTO(resultObj);
    }


    /**
     * 保存或者修改用户数据
     */
    private SysUser saveSysUser(WxUserInfo userInfo, String openid, Date nowTime) {
        SysUser userVo = userService.selectUserByUserName(openid);
        if (null == userVo) {
            userVo = new SysUser();
            userVo.setPassword(openid);
            userVo.setUserName(openid);
            userVo.setNickName(userInfo.getNickName());
            userVo.setAvatar(userInfo.getAvatarUrl());
            userVo.setSex(userInfo.getGender() + "");
            userVo.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
            userVo.setPassword(SecurityUtils.encryptPassword(openid));
            userService.insertUser(userVo);
        } else {
            userVo.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
            userVo.setLoginDate(nowTime);
            userService.updateUser(userVo);
        }
        return userVo;
    }

    /**
     * token 放入缓存中
     */
    private void setTokenInCache(SysUser userVo) {
        getLoginUser().setUser(userVo);
    }

    //替换字符串
    private static String getWebAccess(String CODE) {
        return String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                "wxd176454e3563478f", "fa8b4f0e2d06eeb7361e1d1832a562b5",
                CODE);
    }

    private static String getSha1(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes(StandardCharsets.UTF_8));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] buf = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }
}